package isisv1

import (
	"fmt"
	"strconv"
	"strings"
	"topobuild/base"
	"topobuild/simu"
)

type IsisV1 struct {
	tb_nodes []TableIsisv1Node
	tb_intfs []TableIsisv1Intf
}

func NewIsisV1() *IsisV1 {
	return &IsisV1{}
}

// 将110.20.0.3格式的IP地址转换为10.0000.1100.2000.0003.00
func genNetAddr(ip string) string {
	ip = strings.TrimSuffix(ip, "/24")
	lis := strings.Split(ip, ".")
	if len(lis) != 4 {
		return ""
	}
	// string convert to int
	ips := ""
	for i := 0; i < 4; i++ {
		val, err := strconv.Atoi(lis[i])
		if err != nil {
			return ""
		}
		ips += fmt.Sprintf("%03d", val)
	}
	// 10.0000.1100.2000.0003.00
	return fmt.Sprintf("10.0000.%s.%s.%s.00", ips[0:4], ips[4:8], ips[8:12])
}

// type TableIsisv1Intf struct {
// 	DevName      string `json:"dev_name"`
// 	DevIp        string `json:"dev_ip"`
// 	PortIp       string `json:"port_ip"`
// 	PortName     string `json:"port_name"`
// 	CircuitLevel string `json:"circuit_level"`
// 	Metric       int    `json:"metric"`
// }

func (isis *IsisV1) GenTableInterface(sk *simu.SimuKeeper, conf *base.Config, outfile string) {

	fmtPortIp := func(ip string) string {
		if !strings.HasSuffix(ip, "/24") {
			return ip + "/24"
		}
		return ip
	}

	rlist := make([]TableIsisv1Intf, 0)

	for _, aa := range conf.AsAreas {
		localAS := aa.As
		if localAS <= 0 {
			continue
		}
		for _, dia := range aa.DevInAs {
			devName := dia.Dev
			for _, id := range dia.Intfs {
				var isIntf *TableIsisv1Intf = nil
				if id.Port == "loopback0" {
					isIntf = &TableIsisv1Intf{
						DevName:      devName,
						DevIp:        strings.TrimSuffix(id.PortIp, "/24"),
						PortIp:       fmtPortIp(id.PortIp),
						PortName:     id.Port,
						CircuitLevel: "level2",
						Metric:       1000,
					}
				} else {
					peerDev, _ := conf.FindPeerDev(devName, id.Port, id.PortIp)
					peerAS := conf.GetDevAs(peerDev)
					lo0Ip := conf.GetDevLoopBack0Ip(devName)
					if peerAS == localAS {
						isIntf = &TableIsisv1Intf{
							DevName:      devName,
							DevIp:        strings.TrimSuffix(lo0Ip, "/24"),
							PortIp:       fmtPortIp(id.PortIp),
							PortName:     id.Port,
							CircuitLevel: "level2",
							Metric:       1000,
						}
					}
				}
				// 存储
				if isIntf != nil {
					rlist = append(rlist, *isIntf)
				}
			}
		}
	}

	// 保存一些数据
	isis.tb_intfs = rlist
	WriteIntfXlsx(outfile, rlist)
}

func (isis *IsisV1) GenTableNode(sk *simu.SimuKeeper, conf *base.Config, outfile string) {

	rlist := make([]TableIsisv1Node, 0)

	for _, aa := range conf.AsAreas {
		for _, dia := range aa.DevInAs {
			devName := dia.Dev
			for _, id := range dia.Intfs {
				if id.Port != "loopback0" {
					continue
				}
				devId := id.PortIp
				devId = strings.TrimSuffix(devId, "/24")
				tinode := &TableIsisv1Node{
					DevName:       devName,
					DevIp:         devId,
					IsisProcessId: 1,
					NetAddr:       genNetAddr(devId),
					IsisLevel:     "level2",
					DevId:         devId,
				}
				rlist = append(rlist, *tinode)
			}
		}
	}

	// 保存一些数据
	isis.tb_nodes = rlist
	WriteNodeXlsx(outfile, rlist)
}
